function varargout = TLBitClearDlg(action, varargin)

% TL_BITCLEAR_DLG manages the user interface for TargetLink BitClear block
%
% SYNTAX dlgInfo = TLBitclearDlg('GetDlgInfo');
%   gets dialog info of TargetLink BitClear block
%
%   INPUT ARGUMENTS
%     - / -
%
%   OUTPUT ARGUMENTS
%   dlgInfo       dialog information contains pageNames etc.
%
% SYNTAX [sheetDims, ctrlPos] = ...
%           TLBitclearDlg('CtrlPositions', pageName, commonGeom, dlgInfo, sheetDims);
%   calculates the control positions of all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometry data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%
%   OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% SYNTAX dlgdata = TLBitclearDlg('Create', pageName, dlgfig, dlgdata)
%   creates all controls of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX [dlgdata,bModified] = TLBitclearDlg('Manage', pageName, dlgfig, dlgdata, pageAction);
%   manages all actions of dialog page: <pageName>
%
%   INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageAction      modified control of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%
% SYNTAX dlgdata = TLBitclearDlg('Update', dlgfig, dlgdata, pageNum)
%   updates all controls of dialog page: <pageNum>
%
%   INPUT ARGUMENTS
%   dlgfig          figure handle
%   dlgdata         dialog data
%   pageNum         number of current page
%
%   OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%
% SYNTAX TLBitclearDlg('Apply', dlgfig, dlgdata);
%   writes current blockdata to block and DD
%
%   INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
%   OUTPUT ARGUMENTS
%   - / -


% Author(s): D. Andoleit, T. Pietzsch
% $RCSfile: TLBitclearDlg.m $
% $ProjectName: e:/ARC/Components/HostSW/SimulinkBlocksets/TLBlocksets/CommonBlockset/CommonBlockset_SimBlocksUI/Sources/MSrc/project.pj $
% $Revision: 1.9 $
% $Date: 2011/07/21 15:17:12MESZ $
%
% Copyright ?2011 dSPACE GmbH. All rights reserved.


% switch-case block for possible actions
switch lower(action)
    case 'getdlginfo'
        [varargout{1:2}] = FcnGetDlgInfo(varargin{1});
    case 'ctrlpositions'
        [varargout{1:2}] = FcnCtrlPositions(varargin{:});
    case 'create'
        [varargout{1}]   = FcnCreate(varargin{:});
    case 'manage'
        [varargout{1:2}] = FcnManage(varargin{:});
    case 'managesystemicons',
        [varargout{1:2}] = FcnManageSystemIcons(varargin{:});
    case 'update'
        [varargout{1}]   = FcnUpdate(varargin{:});
    case 'apply'
        [varargout{1:2}] = FcnApply(varargin{:});
    otherwise
        error(['Invalid action "' action '"']);
end


%-----------------------------------------------------------------------------------------
% FcnManageSystemIcons manage actions of toolbar icons
%
% INPUT ARGUMENTS
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%   action      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%   bModified   flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageSystemIcons(dlgfig, dlgdata, action) %#ok

bModified = false;
switch action
    case 'EditCode'
        % look for associated production code file
        [codefile,blockstr] = get_codefile(dlgdata.model);
        if ~isempty(codefile)
            codeedit(codefile,blockstr);
        end

    case 'ViewCode'
        tl_create_links_to_model('ShowComputation',dlgdata.model, 'output');

    otherwise
        error('Invalid callback');

end % switch(action)


%--------------------------------------------------------------------------
% FcnGetDlgInfo gets dialog info of TargetLink bitclear block
%
% INPUT ARGUMENTS
%   hBlock      current block handle
%
% OUTPUT ARGUMENTS
%   dlgInfo     dialog information contains pageNames etc.
%   tlData      TargetLink block data
%--------------------------------------------------------------------------
function [dlgInfo, tlData] = FcnGetDlgInfo(hBlock)

dlgInfo = tl_get_dlginfodefaults('tlsim');
        titleName = 'Bit Clear';
        pathinfo = tl_pathinfo(hBlock);
        dlgInfo.title = sprintf('TargetLink %s: %s', titleName, pathinfo.shortDisplayName);
dlgInfo.pageNames = {...
    'Output & Logging',...
    'Documentation'};
tlData = get_tlcg_data(hBlock);

%--------------------------------------------------------------------------
% FcnCtrlPositions calculates the cotrol positions of all controls of
% dialog page: <pageName>
%
% INPUT ARGUMENTS
%   pageName        name of current page
%   commonGeom      common geometrie data
%   dlgInfo         dialog information contains pageNames etc.
%   sheetDims       dimension of sheet
%   bCodeComment    should code comment be available
%   dlgdata         dialog data
%
% OUTPUT ARGUMENTS
%   sheetDims   modified dimension of sheet
%   ctrlPos     positions of controls
%--------------------------------------------------------------------------
function [sheetDims, ctrlPos] = FcnCtrlPositions(pageName, commonGeom, dlgInfo, sheetDims)  %#ok<INUSL>
% initialize output parameter                                
ctrlPos = [];                         
switch pageName
    case 'Output & Logging'
       [sheetDims,ctrlPos] = FcnCalcOutputControlPositions(commonGeom);
    case 'Documentation'
        bTblBlock = 0;
        bCodeComment = 1;
        [sheetDims, ctrlPos] = TLManageDocCtrls('ctrlpos', commonGeom, ...
            sheetDims, bCodeComment, bTblBlock);
end


%--------------------------------------------------------------------------
% FcnCreate creates all controls of dialog page: <pageName>
%
% INPUT ARGUMENTS
%   pageName    name of current page
%   dlgfig      current figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnCreate(pageName, dlgfig, dlgdata)
pageNum  = strmatch(pageName, dlgdata.pageNames, 'exact');
switch pageName
    case 'Output & Logging'
        dlgdata = FcnCreateOutputControls(pageNum, dlgfig, dlgdata);

    case 'Documentation'
        dlgdata = TLManageDocCtrls( ...
            'create', pageNum, dlgfig, dlgdata);
end
% ctrlPos are not needed anymore
dlgdata.pageData{pageNum}.ctrlPos = [];


%--------------------------------------------------------------------------
% FcnManage manage all actions of dialog page: <pageName>
%
% INPUT ARGUMENTS
%   pageName        name of current page
%   dlgfig          name of current page
%   dlgdata         dialog data
%   pageAction      name of calling control
%
% OUTPUT ARGUMENTS
%   dlgdata     dialog data
%   bModified   flag = 1, if dialog data are modified, = 0 otherwise
%--------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManage(pageName, dlgfig, dlgdata, pageAction)
bModified = false;
pageNum    = strmatch(pageName,dlgdata.pageNames,'exact');
switch pageName
    case 'Output & Logging'
        [dlgdata, bModified] = FcnManageOutputControls(pageNum, dlgfig, ...
                                                        dlgdata,pageAction);
    case 'Documentation'
         [dlgdata, bModified] = TLManageDocCtrls('callback', ...
                                        pageNum, dlgfig, dlgdata, pageAction);
end

%--------------------------------------------------------------------------
% FcnUpdate updates all controls of dialog page: <pageNum>
%
% INPUT ARGUMENTS
%   dlgfig          name of current page
%   dlgdata         dialog data
%   pagenum         number of current tab
%
% OUTPUT ARGUMENTS
%   dlgdata         dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdate(dlgfig, dlgdata, pageNum)
pageName  = dlgdata.pageNames{pageNum};
switch pageName
    case 'Output & Logging'
        dlgdata = FcnUpdateOutputControls(dlgfig,dlgdata,pageNum);
    case 'Documentation'
        TLManageDocCtrls('update', pageNum, dlgfig, dlgdata);
end


%--------------------------------------------------------------------------
% FcnApply writes current blockdata to block and DD
%
% INPUT ARGUMENTS
%   -/-
%
% OUTPUT ARGUMENTS
%   argout      return value is bContinue
%--------------------------------------------------------------------------
function [dlgdata, bClose] = FcnApply(dlgfig, dlgdata, bClose) %#ok<INUSL>
% ask for variable type, if apply-button was pressed after a new
% variable was entered in the variable field.
if ~isempty(dlgdata.data.output.variable)
    bExistOutputVar = logical(dsdd('Exist', dlgdata.data.output.variable, ...
        'Parent',       '/Pool/Variables', ...
        'objectKind',   'Variable'));
    if ~bExistOutputVar
        typeSelection = tl_dsdddlgif( 'SelectObject', ...
            'CurrentPath',  dlgdata.data.output.type, ...
            'ObjectKind',   'Typedef', ...
            'BlockType',    dlgdata.maskType, ...
            'BlockVar',     'output');    
        if ~isempty(typeSelection)
            dlgdata.data.output.type = typeSelection;
            % create variable objects in data dictionary
            tl_export_blockdata_dd(dlgdata.data,'BlockType',dlgdata.maskType,'BlockHandle',dlgdata.model);
        end
    end
end
[dlgdata, bClose] = tl_apply_blockdata(dlgdata, bClose);

%-----------------------------------------------------------------------------------------
% FcnCalcOutputControlPositions calculates positions for all controls on output page
%
% INPUT ARGUMENTS
%   commonGeom      common geometrie information
%
% OUTPUT ARGUMENTS
%   sheetDims       modified dimension of sheet
%   ctrlPos         positions of controls
%
% HINT:
% Positions are calculated from the bottom left of the figure to avoid
% dependencies on figure size
%-----------------------------------------------------------------------------------------
function [sheetDims,ctrlPos] = FcnCalcOutputControlPositions(commonGeom)

% calculate positions of output controls
excludedCtrls = {'allscaling','inheritproperties', 'castoutput', 'width', ...
                'element', 'scaling', 'scalarExp', 'unit', 'type'};
[sheetDims, ctrlPosOutputFrame, colOutputFrame, colDelta] =  ...
    tl_calc_ctrls_positions(commonGeom, excludedCtrls);

% calculate positions of logging controls
excludedCtrls = {'autoscaling'};
[sheetDims, ctrlPos] = ...
    TLManageLoggingCtrls('calcCtrls', commonGeom, sheetDims, excludedCtrls);

% merge position structs
fieldNameList = fieldnames(ctrlPosOutputFrame);
fieldNameList = reshape(fieldNameList,1,length(fieldNameList));
for fieldName = fieldNameList,
    ctrlPos.(fieldName{1}) = ctrlPosOutputFrame.(fieldName{1});
end

% adapt box cordinates in consideration of missing unit controls
ctrlPos.descEdit(3) = ctrlPos.nameEdit(1) + ctrlPos.nameEdit(3) + ctrlPos.nameMenuButton(3) ...
                            - ctrlPos.descEdit(1);

% adapt cordinates of logging box to output box
ctrlPos.samplesLabel(1) = colOutputFrame(4);
ctrlPos.samplesEdit(1)  = ctrlPos.samplesLabel(1) + ...
                            ctrlPos.samplesLabel(3) + commonGeom.frameDelta;
ctrlPos.samplesEdit(3)  = ctrlPosOutputFrame.addressEdit(1) + ...
                            ctrlPosOutputFrame.addressEdit(3) - ctrlPos.samplesEdit(1);
                        
ctrlPos.logPopup(1) = colOutputFrame(2);
ctrlPos.logPopup(3) = colOutputFrame(4) - colOutputFrame(2) - colDelta/3;
ctrlPos.plotEdit(1) = colOutputFrame(2);
ctrlPos.plotEdit(3) = colOutputFrame(4) - colOutputFrame(2) - colDelta/3;
strings_and_styles = {...
    'Bit Index:',               'text'; ...
    '+',                        'pushbutton'; ...
        '(Index is zero based)', 'text'};

    [bitIndexLabelSize, ...
    upDownButtonSize, ...
    bitIndexLeastSigLabelSize] = ...
    ds_get_uicontrol_sizes(commonGeom,strings_and_styles);

% recalculate group boxes' width
groupBoxWidth = ctrlPos.descEdit(1) + ctrlPos.descEdit(3) + commonGeom.frameSideEdgeBuffer;
ctrlPos.logplotGroupbox(3) = groupBoxWidth;
ctrlPos.tlcgoptGroupbox(3) = groupBoxWidth;
ctrlPos.bitIndexGroupbox(3) = groupBoxWidth;
ctrlPos.tlcgoptGroupbox(2) = ctrlPos.tlcgoptGroupbox(2) + ctrlPos.logplotGroupbox(4) + commonGeom.textHeight;

% define an additional box for bitIndex
ctrlPos.bitIndexGroupbox(1) = ctrlPos.tlcgoptGroupbox(1);
ctrlPos.bitIndexGroupbox(2) = ctrlPos.tlcgoptGroupbox(2) + ...
    ctrlPos.tlcgoptGroupbox(4) + commonGeom.textHeight;
ctrlPos.bitIndexGroupbox(4) = commonGeom.editHeight + ...
    commonGeom.frameTopEdgeBuffer + commonGeom.frameBottomEdgeBuffer;

% all controls lie in one row
cy = commonGeom.frameBottomEdgeBuffer;

% bitIndex Label
cx = colOutputFrame(1);
ctrlPos.bitIndexLabel = [cx cy bitIndexLabelSize];

% bitIndex edit field
cx = colOutputFrame(2);
width = ctrlPos.plotEdit(3);
height = commonGeom.editHeight;
ctrlPos.bitIndexEdit = [cx, cy, width, height];

cx = colOutputFrame(4);
ctrlPos.labelLeastSigBit = [cx cy  bitIndexLeastSigLabelSize];

% calculate sheet Dimensions
width = ctrlPos.tlcgoptGroupbox(3) ...
    + 2 * commonGeom.frameSideEdgeBuffer;
height = ctrlPos.logplotGroupbox(4) ...
    + ctrlPos.tlcgoptGroupbox(4) ...
    + ctrlPos.bitIndexGroupbox(4) ...
    + 3 * commonGeom.textHeight ...
    + commonGeom.sheetBottomEdgeBuffer;

sheetDims = [width height];


%-----------------------------------------------------------------------------------------
% FcnCreateOutputControls creates the figure window
%
% INPUT ARGUMENTS
%   pageNum     number of current page
%   dlgfig      handle for dialog figure
%   dlgdata     dialog data
%
% OUTPUT ARGUMENTS
%   dlgdata     modified dialog data
%-----------------------------------------------------------------------------------------
function dlgdata = FcnCreateOutputControls(pageNum,dlgfig,dlgdata)
% create logging controls
dlgdata = TLManageLoggingCtrls('create', pageNum, dlgfig, dlgdata);

Children = dlgdata.pageData{pageNum}.children;
ctrlPos  = dlgdata.pageData{pageNum}.ctrlPos;
pageName = dlgdata.pageNames{pageNum};
% create bit index group box
Children.bitIndexGroupbox = uipanel( ...
    'Parent',            dlgfig, ...
    'Title',            {'Bit Index'}, ...
    'Units',            'pixels', ...
    'Position',          ctrlPos.bitIndexGroupbox);

% create bit index controls
Children.bitIndexLabel = uicontrol( ...
    'Parent',           Children.bitIndexGroupbox, ...
    'Style',            'text', ...
    'String',           'Bit Index:', ...
    'Position',         ctrlPos.bitIndexLabel);


% 'Tag' is needed by the test script
Children.bitIndexEdit = uicontrol( ...
    'Tag',              'bitIndexEdit',...
    'Parent',           Children.bitIndexGroupbox, ...
    'BackgroundColor',  'w', ...
    'Style',            'edit', ...
    'String',           '0', ...
    'Position',         ctrlPos.bitIndexEdit, ...
    'Callback',         sprintf('tldlg(''%s'',gcbf,''bitIndexEdit'')',pageName));

Children.biLeastSigBitLabel = uicontrol( ...
    'Parent',           Children.bitIndexGroupbox, ...
    'Style',            'text', ...
    'String',           '(Index is zero based)', ...
    'Position',         ctrlPos.labelLeastSigBit);
dlgdata.pageData{pageNum}.children = Children;

% create standard variable controls
dlgdata = TLManageVariableCtrls('create', pageNum, dlgfig, dlgdata);
% modify panel title
set(dlgdata.pageData{pageNum}.children.tlcgoptGroupbox, 'Title', 'Output');


%-----------------------------------------------------------------------------------------
% FcnManageOutputControls manages control actions of output page
%
% INPUT ARGUMENTS
%   pageNum         number of current page
%   dlgfig          handle for dialog figure
%   dlgdata         dialog data
%   pageAction      action at one control of current page
%
% OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%   bModified       flag = 1, if dialog data are modified, =0 otherwise
%-----------------------------------------------------------------------------------------
function [dlgdata, bModified] = FcnManageOutputControls(pageNum,dlgfig,dlgdata,action)
Children = dlgdata.pageData{pageNum}.children;
switch action
    case 'bitIndexEdit'
        bitIndexEditStr = get(Children.bitIndexEdit, 'String');
        if strcmp(bitIndexEditStr, dlgdata.data.bitindex)
            bModified = false;
        else
            dlgdata.data.bitindex = bitIndexEditStr;
            bModified = true;
        end
    case {'logPopup', 'plotEdit', 'samplesEdit'}
        [dlgdata, bModified] = ...
            TLManageLoggingCtrls('manage', pageNum, dlgdata, ...
                action, 'logdata');
    otherwise
        [dlgdata, bModified] = TLManageVariableCtrls( ...
                    'manage', pageNum, dlgfig, dlgdata, action, 'output');
end

%-----------------------------------------------------------------------------------------
% FcnUpdateOutputControls updates output controls
%
% INPUT ARGUMENTS
%   dlgfig          figure handle of dialog
%   dlgdata         dialog data
%   pageNum         page Number
%
% OUTPUT ARGUMENTS
%   dlgdata         modified dialog data
%--------------------------------------------------------------------------
function dlgdata = FcnUpdateOutputControls(dlgfig,dlgdata,pageNum)

% update all controls
dlgdata =   TLManageVariableCtrls('update', pageNum, dlgdata, 'output');
dlgdata =   TLManageLoggingCtrls('update', pageNum, dlgdata,'logdata','output');
Children = dlgdata.pageData{pageNum}.children;

% if field "variable" is not empty, check if it has already an error. If it has
% no error, check if it has the right data type in the DD.
if ~strcmp(dlgdata.data.output.variable, '')
    % check if variable edit has already an error
    userData = get(Children.varEdit, 'UserData');
    errorCode = userData.ctrlStatus.iserror;
    % if variable has no error, check if its type is integer in DD
    if errorCode==0
        variableFlag = tl_dsdddlgif( 'IsCompatible', ...
            'CurrentPath',  dlgdata.data.output.variable, ...
            'ObjectKind',   'Variable', ...
            'BlockType',    dlgdata.maskType, ...
            'BlockVar',     'output');    

        % if variable exists in DD and has a wrong data type
        if variableFlag == 2
            userData.ctrlStatus.iserror = 1;
            set(Children.varEdit, 'UserData', userData);
            % set new error code
        end
    end
end

% check bitindex edit
userData.ctrlStatus.iserror = false;
value = str2num(dlgdata.data.bitindex); %#ok<ST2NM>
if ~isempty(value)
    if any(value<0) || ~isreal(value) || any(isnan(value)) || any(round(value) ~= value)
        userData.ctrlStatus.iserror = true;
    end
end
userData.ctrlStatus.enable = 'on';
userData.ctrlStatus.string = dlgdata.data.bitindex;
set(Children.bitIndexEdit, 'UserData', userData);

% set controls
TLManageVariableCtrls('setCtrls', pageNum, dlgfig, dlgdata);
TLManageLoggingCtrls('setCtrls',pageNum, dlgfig, dlgdata);
bitIndexControls = {'bitIndexEdit'};
TLSetCtrlsStatus(dlgfig, Children, bitIndexControls);
